﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using AForge;
using AForge.Controls;
using AForge.Video;
using AForge.Video.DirectShow;
using System.IO;
using FaceBLL;
using FaceModel;
using System.Web.Script.Serialization;
using Newtonsoft.Json.Linq;




namespace WebApplication1.Controllers
{

    public class HomeController : Controller
    {
        #region View 跳转
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "BaiduAI人脸识别训练demo.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Contact:";

            return View();
        }

        public ActionResult FaceRegister()
        {
            return View();
        }

        public ActionResult FaceRecognize()
        {
            return View();
        }
        #endregion


        #region 人脸识别的相关操作

        /// <summary>
        /// 人脸注册
        /// </summary>
        /// <returns></returns>
        public JsonResult Face_Registration()
        {
            //设置APPID/AK/SK
            var API_KEY = "XFPA49myCG7S37XP1DxjLbXF";                   //你的 Api Key
            var SECRET_KEY = "ZvZKigrixMLXNZOLmkrG6iDx9QprlGuT";        //你的 Secret Key

            //var API_KEY = "pY1DpVebGtw7NWVquTvClFOl";                   
            //var SECRET_KEY = "IaLjsM1meKZFbrIU04ddDo4auxvKFow1";

            //SDK初始化
            var client = new Baidu.Aip.Face.Face(API_KEY, SECRET_KEY);
            client.Timeout = 60000;  // 修改超时时间

            //获取人脸照片
            var imageType = "BASE64";  //image_type参数，传入BASE64字符串或URL字符串或FACE_TOKEN字符串
            string imgData64 = Request["imgData64"];
            imgData64 = imgData64.Substring(imgData64.IndexOf(",") + 1);      //将‘，’以前的多余字符串删除

            ResultInfo result = new ResultInfo();
            try
            {
                
                var groupId = "group1";
                var userId = "user1";

                #region 首先查询是否存在人脸
                var result2 = client.Search(imgData64, imageType, userId);  //会出现222207（未找到用户）这个错误
                var strJson = Newtonsoft.Json.JsonConvert.SerializeObject(result2);
                var o2 = Newtonsoft.Json.JsonConvert.DeserializeObject(strJson) as JObject;
                #endregion


                #region 寻找人脸

                //判断是否存在当前人脸，相识度是否大于80
                if (o2["error_code"].ToString() == "0" && o2["error_msg"].ToString() == "SUCCESS")
                {
                    var result_list = Newtonsoft.Json.JsonConvert.DeserializeObject(o2["result"].ToString()) as JObject;
                    var user_list = result_list["user_list"];
                    var Obj = JArray.Parse(user_list.ToString());
                    foreach (var item in Obj)
                    {
                        //80分以上可以判断为同一人，此分值对应万分之一误识率
                        var score = Convert.ToInt32(item["score"]);
                        if(score>80)//相识度值可根据实际应用需求的精确度进行调整
                        {
                            result.info = result2.ToString();
                            result.res = true;
                            result.startcode = 221;
                            return Json(result, JsonRequestBehavior.AllowGet);
                        }
                    }
                }
                #endregion

                #region 带参数调用人脸注册
                var guid = Guid.NewGuid();
                // 调用人脸注册，可能会抛出网络等异常，使用try/catch捕获
                // 可选参数
                var options = new Dictionary<string, object>
                {
                    {"user_info", guid}
                 };
                var resultData = client.UserAdd(imgData64, imageType, groupId, userId, options);
                result.info = resultData.ToString();
                result.res = true;
                result.other = guid.ToString();
                #endregion
            }
            catch (Exception e)
            {
                result.info = e.Message;
            }
            return Json(result, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 用户信息入库
        /// </summary>
        /// <returns></returns>
        public JsonResult face_userInfoSace()
        {
            ResultInfo result = new ResultInfo();

            try
            {
                //这里就不进行非空判断了，后期根据实际情况进行优化
                var UserName = Request["UserName"];
                var Month = Request["Month"];
                var Sex = Request["Sex"];
                var Works = Request["Works"];
                var face_token = Request["face_token"];
                var Guid_Id = Request["Guid_Id"];

                Face_UserInfo model = new Face_UserInfo();
                model.UserName = UserName;
                model.Month = Month;
                model.Sex = Sex;
                model.Works = Works;
                model.face_token = face_token;
                model.Guid_Id = Guid_Id;

                //根据人脸唯一标识判断是否存在数据
                List<Face_UserInfo> strlist = new Face_UserInfoBLL().GetfaceinfoByToken(Guid_Id);
                if(strlist.Count>0)
                {
                    result.res = true;
                    result.info = "当前用户已注册过！";
                    return Json(result, JsonRequestBehavior.AllowGet);
                }

                if(new Face_UserInfoBLL().face_userInfoSace(model)>0)
                {
                    result.res = true;
                    result.info = "注册成功";
                }
                else
                    result.info = "注册失败";
            }
            catch (Exception e)
            {
                result.info = e.Message;
            }
            return Json(result, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 人脸识别
        /// </summary>
        /// <returns></returns>
        public JsonResult Face_Distinguish()
        {
            // 设置APPID/AK/SK
            var API_KEY = "XFPA49myCG7S37XP1DxjLbXF";                   //你的 Api Key
            var SECRET_KEY = "ZvZKigrixMLXNZOLmkrG6iDx9QprlGuT";        //你的 Secret Key

            //var API_KEY = "pY1DpVebGtw7NWVquTvClFOl";                   
            //var SECRET_KEY = "IaLjsM1meKZFbrIU04ddDo4auxvKFow1";        

            //SDK初始化
            var client = new Baidu.Aip.Face.Face(API_KEY, SECRET_KEY);
            client.Timeout = 60000;  // 修改超时时间

            //获取图片的Base64字符串
            var imageType = "BASE64";  //image_type参数，传入BASE64字符串或URL字符串或FACE_TOKEN字符串
            string imgData64 = Request["imgData64"];
            imgData64 = imgData64.Substring(imgData64.IndexOf(",") + 1);      //将‘，’以前的多余字符串删除

            ResultInfo result = new ResultInfo();
            try
            {
                var groupId = "group1";
                var userId = "user1";
                var detectResult = client.Detect(imgData64, imageType);

                #region 活体检测

                //活体检测阈值是多少
                //0.05 活体误拒率：万分之一；拒绝率：63.9%
                //0.3 活体误拒率：千分之一；拒绝率：90.3%
                //0.9 活体误拒率：百分之一；拒绝率：97.6%
                //1误拒率: 把真人识别为假人的概率. 阈值越高，安全性越高, 要求也就越高, 对应的误识率就越高
                //2、通过率=1-误拒率
                //所以你thresholds参数返回 和 face_liveness 比较大于推荐值就是活体

                //并检测是不是活体
                var faces = new JArray
                {
                    new JObject
                    {
                        {"image", imgData64},
                        {"image_type", "BASE64"}
                    }
                };
                var Living = client.Faceverify(faces);  //活体检测交互返回
                var LivingJson = Newtonsoft.Json.JsonConvert.SerializeObject(Living);
                var LivingObj = Newtonsoft.Json.JsonConvert.DeserializeObject(LivingJson) as JObject;
                if (LivingObj["error_code"].ToString() == "0" && LivingObj["error_msg"].ToString() == "SUCCESS")
                {
                    var Living_result = Newtonsoft.Json.JsonConvert.DeserializeObject(LivingObj["result"].ToString()) as JObject;
                    var Living_list = Living_result["thresholds"];
                    double face_liveness = Convert.ToDouble(Living_result["face_liveness"]);
                    var frr = Newtonsoft.Json.JsonConvert.SerializeObject(Living_list.ToString());
                    var frr_1eObj = Newtonsoft.Json.JsonConvert.DeserializeObject(Living_list.ToString()) as JObject;
                    double frr_1e4 = Convert.ToDouble(frr_1eObj["frr_1e-4"]);
                    if (face_liveness < frr_1e4)
                    {
                        result.info = "识别失败：不是活体！";
                        return Json(result, JsonRequestBehavior.AllowGet);
                    }
                }
                #endregion

                #region 首先查询是否存在人脸
                var result2 = client.Search(imgData64, imageType, groupId);
                var strJson = Newtonsoft.Json.JsonConvert.SerializeObject(result2);
                var o2 = Newtonsoft.Json.JsonConvert.DeserializeObject(strJson) as JObject;

                #endregion

                #region 判断是否存在当前人脸，相识度是否大于80

                if (o2["error_code"].ToString() == "0" && o2["error_msg"].ToString() == "SUCCESS")
                {
                    var result_list = Newtonsoft.Json.JsonConvert.DeserializeObject(o2["result"].ToString()) as JObject;
                    var user_list = result_list["user_list"];
                    var Obj = JArray.Parse(user_list.ToString());
                    foreach (var item in Obj)
                    {
                        //80分以上可以判断为同一人，此分值对应万分之一误识率
                        var score = Convert.ToInt32(item["score"]);
                        if (score > 80)
                        {
                            result.info = result2.ToString();
                            result.res = true;
                            result.startcode = 221;
                            return Json(result, JsonRequestBehavior.AllowGet);
                        }
                    }
                }
                else
                {
                    result.info = strJson.ToString();
                    result.res = false;
                    return Json(result, JsonRequestBehavior.AllowGet);
                }
                #endregion
            }
            catch (Exception e)
            {
                result.info = e.Message;
            }
            return Json(result, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 识别成功，查询数据库
        /// </summary>
        /// <returns></returns>
        public JsonResult Face_UserInfoList()
        {
            ResultInfo result = new ResultInfo();
            //这里就不进行非空判断了，后期根据实际情况进行优化
            var Guid_Id = Request["Guid_Id"];
            //根据人脸唯一标识判断是否存在数据
            List<Face_UserInfo> strlist = new Face_UserInfoBLL().GetfaceinfoByToken(Guid_Id);
            var strJson = Newtonsoft.Json.JsonConvert.SerializeObject(strlist);
            result.info = strJson;
            result.res = true;
            return Json(result, JsonRequestBehavior.AllowGet);
        }

        #endregion


        #region 图片上传到服务器 Base64解码

        /// <summary>
        /// 图片上传 Base64解码
        /// </summary>
        /// <param name="dataURL">Base64数据</param>
        /// <param name="path">保存路径</param>
        /// <param name="imgName">图片名字</param>
        /// <returns>返回一个相对路径</returns>

        public JsonResult decodeBase64ToImage(string dataURL, string imgName)
        {
            string filename = "";//声明一个string类型的相对路径

            String base64 = dataURL.Substring(dataURL.IndexOf(",") + 1);      //将‘，’以前的多余字符串删除

            System.Drawing.Bitmap bitmap = null;//定义一个Bitmap对象，接收转换完成的图片
            ResultInfo result = new ResultInfo();
            try//会有异常抛出，try，catch一下
            {
                String inputStr = base64;//把纯净的Base64资源扔给inpuStr,这一步有点多余

                byte[] arr = Convert.FromBase64String(inputStr);//将纯净资源Base64转换成等效的8位无符号整形数组

                System.IO.MemoryStream ms = new System.IO.MemoryStream(arr);//转换成无法调整大小的MemoryStream对象
                System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(ms);//将MemoryStream对象转换成Bitmap对象
                ms.Close();//关闭当前流，并释放所有与之关联的资源
                bitmap = bmp;
                filename = "/upload/" + imgName + ".png";//所要保存的相对路径及名字
                string tmpRootDir = Server.MapPath(System.Web.HttpContext.Current.Request.ApplicationPath.ToString()); //获取程序根目录 
                string imagesurl2 = tmpRootDir + filename.Replace(@"/", @"\"); //转换成绝对路径 

                bitmap.Save(imagesurl2, System.Drawing.Imaging.ImageFormat.Png);//保存到服务器路径
                result.info = imagesurl2;  //返回相对路径
                result.res = true;
            }
            catch (Exception)
            {
            }
            return Json(result, JsonRequestBehavior.AllowGet);
        }


        #endregion

       
        /// <summary>
        /// 枚举所有视频输入设备(暂时不使用)
        /// </summary>
        /// <returns></returns>
        /// <exception cref="ApplicationException"></exception>
        public string videoDevices()
        {
            //枚举所有视频输入设备
            FilterInfoCollection videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

            if (videoDevices.Count == 0)
                throw new ApplicationException();

            string bb = "";
            foreach (AForge.Video.DirectShow.FilterInfo device in videoDevices)
            {
                bb+=device.Name+",";
            }
            bb = bb.Substring(0, bb.Length - 1);
            return bb;
        }

        /// <summary>
        /// 定义一个返回类型的实体
        /// </summary>
        public class ResultInfo {
            public ResultInfo() {  //默认值
                res = false;
                startcode = 449;
                info = "";
                other = "";
            }
            public bool res { get; set; }  //返回状态（true or false）
            public int startcode { get; set; } //返回http状态码
            public string info { get; set; }  //返回结果
            public string other { get; set; }  //其他
        }

    }
}